package com.kylin.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.kylin.common.core.beans.ResultBean;
import com.kylin.common.core.exception.BaseException;
import com.kylin.gateway.service.ValidateCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 验证码过滤器
 * 
 * @author wuhao
 */
@Component
public class ValidateCodeFilter extends AbstractGatewayFilterFactory<ValidateCodeFilter.Config>
{
    @Autowired
    private ValidateCodeService validateCodeService;

    /**
     * 配置示例
     * #验证码处理
     *   - name: ValidateCodeFilter
     *     args:
     *       urls:
     *         - /auth/oauth/token
     *         - /auth/notify/code
     */

    public ValidateCodeFilter() {super(Config.class);}

    private static final String CODE = "code";

    private static final String UUID = "uuid";

    @Override
    public GatewayFilter apply(Config config)
    {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            if (config.getUrls().stream().filter(item -> item.contains(request.getURI().getPath())).collect(Collectors.toList()).isEmpty() ){
                return chain.filter(exchange);
            }
            // 解决auth/token 有些不需要验证码校验的过程 add by wuhao at 20220416
            if(request.getURI().getPath().equals("/auth/oauth/token") && request.getQueryParams().getFirst(UUID) == null) {
                return chain.filter(exchange);
            }
            return checkValidate(exchange, chain);
        };
    }



    /**
     * 验证码校验逻辑处理
     * @return
     * @author wuhao
     * @since 2.2.3 - 2022/4/2
     */
    private Mono<Void> checkValidate(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();

        try
        {
            validateCodeService.checkCaptcha(request.getQueryParams().getFirst(CODE),
                    request.getQueryParams().getFirst(UUID));
        }
        catch (Exception e)
        {
            int code = 500;
            String message = e.getMessage();
            if(e instanceof BaseException) {
                code = ((BaseException) e).getCode();
                message = e.getMessage();
            }
            ServerHttpResponse response = exchange.getResponse();
            return exchange.getResponse().writeWith(
                    Mono.just(response.bufferFactory().wrap(JSON.toJSONBytes(new ResultBean<Object>(code, message)))));
        }
        return chain.filter(exchange);
    }

    public static class Config {
        private List<String> urls;

        public List<String> getUrls() {
            return urls;
        }

        public void setUrls(List<String> urls) {
            this.urls = urls;
        }
    }
}
